<?php
/**
 * @package pmapi
 * @copyright Copyright (c)2014 Enrico Fagnoni
 * @license GNU General Public License version 3, or later
 *
 * @since 1.0.0
 */
 
defined('_JEXEC') or die;

if (!class_exists('LinkedDataView')) require(JPATH_COMPONENT.DS.'views'.DS.'linkeddata.php');

class PmapiViewProduct extends LinkedDataView
{
    const BASE_PRICE = 'PRICE';
    
    protected 
        $product = null,
        $show_prices = array(),
        $show_images = array(),
        $extractedEmbeddedData = array();
    
        
    protected function _computeETag()
    {
        return md5(serialize($this->product));
    }

    
    /**
     * Extract RDF triples embedded into textual product fields:
     *  custom_field_desc semantic can use a simple tagging (i.e. % data% ) to embed  semantic
     *  product_desk can embed semantic using special formatted http comment ( i.e. <!--%PMMETA: data -->)
     * 
     * Embedded data can refer some internal variables using a simple tagging convention (i.e. {variable})
     * Returns an array of data extraction
     */
    private function _extractEmbeddedData()
    {
        $rdfs = array();
        $p = $this->product; // shortcut
        
        // custom_field_desc and image semantic use a simple template engine to embed  semantic
        $templateEngine = SimpleTemplateEngine::factory()->setVars (array (
            // these variables can be used in metadata throug temlates
            // Because of virtuemart ui strip html tag from text input, 
            // you can use {[}http:/example.com/{]} instead of <http:/example.com/>
            'URL'             => '<'.UriHelper::mkDataURL('product',$p->virtuemart_product_id).'>',
            'manufacturerURI' => '<'.UriHelper::mkResourceURI('manufacturer',$p->virtuemart_manufacturer_id).'>',
            'currency'        => '"'.$p->currency.'"',
            'vendorURI'       => '<'.UriHelper::mkResourceURI('user',$p->virtuemart_vendor_id).'>',
            '['               => '<', //trick to bypass virtuemart UI filter on html
            ']'               => '>', //trick to bypass virtuemart UI filter on html
        ));  
               
        
        // extract semantic from  custom fields description: use % % as delimiter to tagging triples
        // use {v} as placeholder for custom field value
        // i.e. %:model gr:hasMPN {v}%
        foreach ($p->customFieldsParents as $parent){    
            if( $parent->custom_field_desc && preg_match('/%(.*)%/', $parent->custom_field_desc,$matches)){
                $rdfs[$parent->custom_title.' parent custom field desc'] = $templateEngine
                    ->setTemplate($matches[1])
                    ->render();
            }
        }
        
        // same as custom fields description, but using parent descriptions
        foreach ($p->customfields as $customfield){    
            if( $customfield->custom_field_desc && preg_match('/%(.*)%/', $customfield->custom_field_desc,$matches)){
                $rdfs[$customfield->custom_title.' custom field desc'] = $templateEngine
                    ->addVar('v',$customfield->custom_value)
                    ->setTemplate($matches[1])
                    ->render();
            }
        }
        // extract semantic from  image meta field: use % % as delimiter to tagging triples
        // use {imageURL} and {thumbURL} as placeholder for image url and thumbnail
        // i.e. %{imageURL} dcterm:right "by Mr.X"%
        foreach ($this->show_images as $idx=>$image){
            if( $image->file_meta && preg_match('/%(.*)%/',$image->file_meta,$matches)){
                $rdfs['image '.$idx.' meta'] = $templateEngine
                    ->addVar('imageURL','<'.$image->file_url.'>')
                    ->addVar('thumbURL','<'.$image->file_url_thumb.'>')
                    ->setTemplate($matches[1])
                    ->render();
            }
        }
       
        //extract metadata from  product internal notes and meta
        if( $p->intnotes && preg_match('/%(.*)%/', $p->intnotes,$matches)){
            $rdfs['intnotes'] = $templateEngine
                ->setTemplate($matches[1])
                ->render();
        }
        if( $p->metadesc && preg_match('/%(.*)%/', $p->metadesc,$matches)){
            $rdfs['metadesc'] = $templateEngine
                ->setTemplate($matches[1])
                ->render();
        }
             
        //extract metadata from  product html description, using a more sophisticated template extractor
        // the idea to embedd a turtle template comes from  http://turtlescript.sourceforge.net/  
        if( $p->product_desc && preg_match('/<script\s+type="application\/com_pmine"\s*>(.*)<\/script\s*>/s', $p->product_desc,$matches)){
            $rdfs['product_desc'] = $templateEngine
                ->setTemplate($matches[1])
                ->render();
        }                    
               
        return $rdfs; 
    }

    
    public function GET_RequestProcessor($tpl = null) 
    {
        $this->product = $this->get('Item');
        $this->show_prices = new DisplayPriceArray($this->product);
        $this->show_images = array();
        
        // Populate prices to be exposed taking into account user permissions:
        //  .) for end users show base price and SRP 
        //  .) for admin or store admin show also INVOICE price      
        if(VmConfig::get('show_prices', 1)){
            if (!class_exists('Permissions')) 
                require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'permissions.php');
            $perms = Permissions::getInstance();
            $perms->getPermissions(); // loads current user permission
            if( $perms->_show_prices) {
                $this->show_prices
                    ->add(self::BASE_PRICE)
                    ->add('SRP');
                if ($perms->atLeastPerms('storeadmin')) $this->show_prices->add('INVOICE');     
            }                  
        }
        
        $this->show_images = ApiHelper::filterAndRebaseImages('product',$this->product->images);                
        $this->extractedEmbeddedData = $this->_extractEmbeddedData();
        
        return parent::GET_RequestProcessor($tpl);
    }
}

/**
 * Prices ready to be rendered taking into account component preferences
 */
class DisplayPriceArray extends ArrayObject
{
    private $product;
    
    function __construct($product) {$this->product=$product;}
    
    function add($type=null)
    {
        static $params = null; if(is_null($params)) $params = JComponentHelper::getParams('com_pmapi');

        $price = new stdClass;        
        $price->type = ($type!=PmapiViewProduct::BASE_PRICE)?$type:null;
        $price->currency = $this->product->currency;
        $price->name = strtolower($type);
        $var = $params->get($price->name);               
        switch ($var) {
            case 'costPrice':
            case 'basePrice':
            case 'basePriceVariant':
            case 'discountedPriceWithoutTax':
            case 'priceWithoutTax':
                $price->value = $this->product->prices[$var];
                $price->taxIncluded = 'false';
                break;
            case 'basePriceWithTax':
            case 'salesPrice':
            case 'salesPriceWithDiscount':
                $price->value = $this->product->prices[$var];
                $price->taxIncluded = 'true';              
                break;
            default:
                $price->taxIncluded = $price->value = false;
                break;
        }
        if ($price->value  > EPSILON ) $this->append($price);

        return $this;        
    }
}
